package com.zzb.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import com.zzb.weixin.constant.WXJsonName;
import com.zzb.weixin.exception.WeiXinException;
import com.zzb.weixin.json.JSON;
import com.zzb.weixin.json.JsonObject;

public class HTTPUtil {

	/**
	 * 在url末端添加参数
	 * 
	 * @param url
	 * @param key
	 * @param value
	 * @return
	 */
	public static String addGetParam(String url, String key, String value) {
		String returnUrl = url == null ? "" : url;
		if (url.indexOf("?") > 0) {
			returnUrl += "&";
		} else {
			returnUrl += "?";
		}
		return returnUrl + key + "=" + value;
	}
	
	/**
	 * 
	 * 执行get请求并将返回内容转为json格式返回
	 */
	public static JsonObject doGet(String url) throws WeiXinException {
		JsonObject accessToken = null;
		InputStream in = null;
		try {
			if (url.startsWith("https")){
				SSLContext sc = SSLContext.getInstance("SSL");
				sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },new java.security.SecureRandom());
				URL console = new URL(url);
				HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
				conn.setSSLSocketFactory(sc.getSocketFactory());
				conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
				conn.connect();
				in = conn.getInputStream();
			}else{
				in = new URL(url).openStream();
			}
			accessToken = JSON.parse(getContext(in));
			doExeption(accessToken);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
			accessToken = new JsonObject();
			accessToken.put(WXJsonName.ERR_CODE, "99999");
			accessToken.put(WXJsonName.ERR_MSG, "自定义错误");
			doExeption(accessToken);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} finally {
			if(in != null){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return accessToken;
	}
	/**
	 * 执行post请求并将返回内容转为json格式返回
	 */
	public static JsonObject doPost(String url, JsonObject message)
			throws WeiXinException {
		JsonObject jo = null;
		PrintWriter out = null;
		InputStream in = null;
		try {
			if (url.startsWith("https")){
				SSLContext sc = SSLContext.getInstance("SSL");
				sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },new java.security.SecureRandom());
				URL console = new URL(url);
				HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
				conn.setSSLSocketFactory(sc.getSocketFactory());
				conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
				conn.connect();
				in = conn.getInputStream();
			}else{
				in = new URL(url).openStream();
			}
			// 打开和URL之间的连接
			URLConnection conn = new URL(url).openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent",
					"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(conn.getOutputStream());
			// 发送请求参数
			out.print(message.toString());
			// flush输出流的缓冲
			out.flush();
			// POST请求

			out.flush();
			out.close();
			in = conn.getInputStream();
			jo = JSON.parse(getContext(in));
			doExeption(jo);
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (ProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if (in != null ){
				try {
					in.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return jo;
	}

	/**
	 * 获取输入流的内容
	 * @param is
	 * @param charsetName
	 * @return
	 * @throws IOException
	 */
	public static String getContext(InputStream is, String charsetName) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader bf = null;
		try {
			bf = new BufferedReader(new InputStreamReader(is,charsetName));
			String s = bf.readLine();
			while (s != null) {
				sb.append(s);
				s = bf.readLine();
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (bf != null)
				bf.close();
		}
		return sb.toString();
	}
	/**
	 * 获取输入流的内容
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static String getContext(InputStream is) throws IOException {
		StringBuilder sb = new StringBuilder();
		BufferedReader bf = null;
		try {
			bf = new BufferedReader(new InputStreamReader(is,"UTF-8"));
			String s = bf.readLine();
			while (s != null) {
				sb.append(s);
				s = bf.readLine();
			}
		} catch (IOException e) {
			throw e;
		} finally {
			if (bf != null)
				bf.close();
		}
		return sb.toString();
	}

	public static void doExeption(JsonObject jo) throws WeiXinException {
		String errCode = jo.getAsString(WXJsonName.ERR_CODE);
		if (errCode == null || "".equals(errCode) || "0".equals(errCode))
			return;
		throw new WeiXinException(jo);
	}
	private static class TrustAnyTrustManager implements X509TrustManager {

		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}

		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}

		public X509Certificate[] getAcceptedIssuers() {
			return new X509Certificate[] {};
		}
	}

	private static class TrustAnyHostnameVerifier implements HostnameVerifier {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	}
}
